package xin.petstore.framework.rpc.dubbo;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import xin.petstore.framework.utils.JsonMapper;

import java.util.Map;

public class DubboClient {
    private static Logger logger = LoggerFactory.getLogger(DubboClient.class);
    private String applicationConfigName;
    private String registryAddress;
    private String registryUsername;
    private String registryPassword;
    private String version;
    private String group;
    private ReferenceConfig<GenericService> reference;

    public void init() {
        Assert.notNull(this.applicationConfigName, "applicationConfig name is not null");
        Assert.notNull(this.registryAddress, "Registry address is not null");

        ApplicationConfig application = new ApplicationConfig();
        application.setName(this.applicationConfigName);

        RegistryConfig registry = new RegistryConfig();
        registry.setAddress(this.registryAddress);
        if (StringUtils.isNotEmpty(this.registryUsername)) {
            registry.setUsername(this.registryUsername);
        }
        if (StringUtils.isNotEmpty(this.registryPassword)) {
            registry.setPassword(this.registryPassword);
        }
        this.reference = new ReferenceConfig();

        this.reference.setApplication(application);

        this.reference.setRegistry(registry);
        this.reference.setGeneric(Boolean.valueOf(true));
    }

    public String singleParsInvoke(String interfaceName, String methodName, String parClass, Map<String, Object> pars) {
        try {
            if (this.reference == null) {
                init();
            }
            this.reference.setInterface(interfaceName);
            if (StringUtils.isNotEmpty(this.version))
                this.reference.setVersion(this.version);
            if (StringUtils.isNotEmpty(this.group))
                this.reference.setGroup(this.group);
            GenericService genericService = (GenericService) this.reference.get();
            Object result = genericService.$invoke(methodName, new String[]{parClass}, new Object[]{pars});
            return JsonMapper.buildNormalMapper().toJson(result);
        } catch (Exception e) {
            logger.error("invoke method error \n", e);
        }
        return null;
    }

    public String multipleParsInvoke(String interfaceName, String methodName, String[] parClass, Object[] pars) {
        try {
            if (this.reference == null)
                init();
            this.reference.setInterface(interfaceName);
            if (StringUtils.isNotEmpty(this.version))
                this.reference.setVersion(this.version);
            if (StringUtils.isNotEmpty(this.group))
                this.reference.setGroup(this.group);
            GenericService genericService = (GenericService) this.reference.get();
            Object result = genericService.$invoke(methodName, parClass, pars);
            return JsonMapper.buildNormalMapper().toJson(result);
        } catch (Exception e) {
            logger.error("invoke method error \n", e);
        }
        return null;
    }

    public String getApplicationConfigName() {
        return this.applicationConfigName;
    }

    public void setApplicationConfigName(String applicationConfigName) {
        this.applicationConfigName = applicationConfigName;
    }

    public String getRegistryAddress() {
        return this.registryAddress;
    }

    public void setRegistryAddress(String registryAddress) {
        this.registryAddress = registryAddress;
    }

    public String getRegistryUsername() {
        return this.registryUsername;
    }

    public void setRegistryUsername(String registryUsername) {
        this.registryUsername = registryUsername;
    }

    public String getRegistryPassword() {
        return this.registryPassword;
    }

    public void setRegistryPassword(String registryPassword) {
        this.registryPassword = registryPassword;
    }

    public String getVersion() {
        return this.version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getGroup() {
        return this.group;
    }

    public void setGroup(String group) {
        this.group = group;
    }
}
